# !/usr/bin/python
# -*- coding: utf-8 -*-
'''
@File    :   198_打家劫舍1.py
@Time    :   2021/11/06 13:53:51
@Author  :   Qingxiang Zhang
@Version :   1.0
@Contact :   344285081@qq.com
@Desc    :   动态规划
@Software:    Vscode
'''

"""你是一个专业的小偷，计划偷窃沿街的房屋。每间房内都藏有一定的现金，影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统，如果两间相邻的房屋在同一晚上被小偷闯入，系统会自动报警。
给定一个代表每个房屋存放金额的非负整数数组，计算你 不触动警报装置的情况下 ，一夜之内能够偷窃到的最高金额。
难度：中等

示例 1：
输入：[1,2,3,1]
输出：4
解释：偷窃 1 号房屋 (金额 = 1) ，然后偷窃 3 号房屋 (金额 = 3)。
     偷窃到的最高金额 = 1 + 3 = 4 。
示例 2：
输入：[2,7,9,3,1]
输出：12
解释：偷窃 1 号房屋 (金额 = 2), 偷窃 3 号房屋 (金额 = 9)，接着偷窃 5 号房屋 (金额 = 1)。
     偷窃到的最高金额 = 2 + 9 + 1 = 12 。
 提示：
1 <= nums.length <= 100
0 <= nums[i] <= 400
"""
"""
#### 解题思路
这个问题不复杂，其实利用一般的迭代可以直接解出来，但是这里讲动态规划，所以还是按照标准的套路来
- **第一步：确定动态规划状态**
  直接定义题目所求的偷窃的最高金额，所以`dp[i]`表示偷窃第`i`号房子能得到的最高金额。
- **第二步：写出状态转移方程**
  如果我们不考虑限制条件相邻两个房子不能抢，那么问题就很简单。想得到第`i`个房间偷窃到的最高金额的时候，我们会考虑子问题前`i-1​`间的最高金额`dp[i-1]`，然后再加上当前房间的金额，所以最后可以表达为`dp[i]=dp[i-1]+nums[i]`。
  需要注意的是，这里限制了相邻两个房子是不能抢的，接下来我们就要考虑两种情况。
  如果抢了第i个房间，那么第`i-1​`肯定是不能抢的，这个时候需要再往前一间，用第`i-2`间的金额加上当前房间的金额，得到的状态转移方程是`dp[i]=dp[i-2]+nums[i]`。
  如果没有抢第`i​`个房间，那么肯定抢了第`i-1`间的金额，所以直接有`dp[i]=dp[i-1]`。
  最后综合一下两种情况，就可以很快得到状态转移方程：`dp[i]=max(dp[i-2]+nums[i],dp[i-1])​`
- **第三步：考虑初始化条件**
  初始化条件需要考虑第一个房子和第二个房子，之后的房子都可以按照规律直接求解，当我们只有一个房子的时候，自然只抢那间房子，当有两间房的时候，就抢金额较大的那间。综合起来就是`dp[0]=nums[0]，dp[1]=max(nums[0],nums[1])​`。
- **第四步:考虑输出状态**
  直接返回状态转移数组的最后一个值就是所求的最大偷窃金额。
- **第五步：考虑对时间，空间复杂度的优化**
  时间复杂度为$O(N)$不能再优化了，空间复杂度方面如果用动态规划是不能优化，但是如果用迭代的方法只存储临时变量来记录每一步计算结果，这样可以降到$O(1)$。
"""
 

class Solution:
    def rob(self, nums) -> int:
        if not nums:
            return 0
        if len(nums)==1:
            return nums[0]
        n = len(nums)
        dp = [0] * n
        dp[0] = nums[0]
        dp[1] = max(nums[0],nums[1])
        for i in range(2,n):
            dp[i] = max(dp[i-2]+nums[i],dp[i-1])
        return dp[-1]
"""
上述方法使用了数组存储结果。考虑到每间房屋的最高总金额只和该房屋的前两间房屋的最高总金额相关，因此可以使用滚动数组，在每个时刻只需要存储前两间房屋的最高总金额。"""


def rob(self, nums) -> int:
  if not nums:
    return 0
  size = len(nums)
  
  if size == 1:
    return nums[0]
  first, second = nums[0], max(nums[0], nums[1])
  for i in range(2, size):
    first, second = second, max(first + nums[i], second)
  return second

  